#ifndef __IDETECT__
#define __IDETECT__

#include "stream.h"
#include "archive.h"
#include "xtab.h"

namespace xm
{
	DEFINE_PROGID(DetectSession);
	DEFINE_PROGID(XManEngine);

	//////////////////////////////////////////////////////////////////////////

	enum SESSION_OPTIONS
	{
		DOSCAN_NOHEUR		= 0x00000001,
		DOSCAN_LOGDR		= 0x00000002,	// DOSCAN_LOGDR will ignore all treats

		DOKILL_IGNORE		= 0x10000000,
		DOKILL_TREAT		= 0x20000000,
		DOKILL_REMOVE		= 0x40000000,
	};

	enum _DETLEV
	{
										// < 0 means NOT MALWARE
		DLEV_NOT_MALW		= -1,
		DLEV_MALW_HEUR		= 0,
		DLEV_MALW_EXACT		= 20000,
		DLEV_MALW_INFECT	= 50000,
	};

	typedef LONG	DETLEV;

	enum TreatReesult
	{
		TREAT_S_OK,
		TREAT_E_DELETE = -1,
	};

	struct DetectResult
	{
		DETLEV		Level;
		UINT32		SigId;
		LPCSTR		Name;
	};

	class IKDetector;

	class IKDetectSession : public IUnknown
	{
	public:
		STDMETHOD(Open)( IUnknown * pstm, UINT32 uOptions ) = 0;
		STDMETHOD(SelectFormat)( FMTID fmtid, UINT32 uOpenFlags = -1 ) = 0;
		STDMETHOD(Close)() = 0;
		STDMETHOD_(IKXoTable*,GlobalXoTable)() = 0;
		STDMETHOD_(IKXoTable*,SessionXoTable)() = 0;
		STDMETHOD_(UINT32,DetectOptions)() = 0;
		STDMETHOD_(IKFileStream*,RawStream)() = 0;
		STDMETHOD_(IKBStream*,TargetStream)() = 0;		// return SetAttachedStream -> RawStream
		STDMETHOD_(IKArchive*,CurrentArchive)() = 0;
		STDMETHOD(PushResult)( DetectResult & result, IKDetector * det = 0 ) = 0;
		STDMETHOD(GetResult)( DetectResult& result, IKDetector** ppDet = 0 ) = 0;
		STDMETHOD(SetTreatResult)( HRESULT hrTreat ) = 0;
		// cWant == 0, return Total; else, return fetched
		STDMETHOD_(SIZE_T,EnumResult)( DetectResult* lpResults, SIZE_T cWant = 0 ) = 0;
		//STDMETHOD_(IKBStream*,AdditionalInfo)() = 0;
		STDMETHOD(SetAttachedStream)( IKBStream * bso ) = 0;
		DECLARE_IID;
	};

	// {AA1E83C1-8ACD-4A4F-A426-83D87560894A}
	DEFINE_IID( IKDetectSession, "{AA1E83C1-8ACD-4A4F-A426-83D87560894A}",
		0xaa1e83c1, 0x8acd, 0x4a4f, 0xa4, 0x26, 0x83, 0xd8, 0x75, 0x60, 0x89, 0x4a);

	enum TREAT_RESULT
	{
		S_DELETE_OK		= S_FALSE,
		S_TREAT_OK		= S_OK,
		E_DELETE_FAIL	= 0x80120100,
		E_TREAT_FAIL	= 0x80120101,
	};

	class IKDetector : public IUnknown
	{
	public:
		STDMETHOD(Detect)( IKDetectSession * sess, DetectResult * pdr ) = 0;
		// TREAT_RESULT please
		STDMETHOD(Treat)( IKDetectSession * sess, DetectResult * pdr ) = 0;
		STDMETHOD(Reset)() = 0;
		DECLARE_IID;
	};

	//DEFINE_IID(IDetection, "{6020E590-7F41-4864-AE68-2F17E9DD6D98}" );

	// {6020E590-7F41-4864-AE68-2F17E9DD6D98}
	DEFINE_IID(IKDetector, "{6020E590-7F41-4864-AE68-2F17E9DD6D98}",
		0x6020e590, 0x7f41, 0x4864, 0xae, 0x68, 0x2f, 0x17, 0xe9, 0xdd, 0x6d, 0x98);

	class IWithParameters : public IUnknown
	{
	public:
		STDMETHOD(PushParameter)( xv::AnyValue& rParam ) PURE;
		DECLARE_IID;
	};

	//DEFINE_IID(IDetectionEx, "{779010D8-6BFD-4E63-891C-6332C34C0D39}");
	// {779010D8-6BFD-4E63-891C-6332C34C0D39}
	DEFINE_IID(IWithParameters, "{779010D8-6BFD-4E63-891C-6332C34C0D39}",
		0x779010d8, 0x6bfd, 0x4e63, 0x89, 0x1c, 0x63, 0x32, 0xc3, 0x4c, 0xd, 0x39);

	enum DETCC
	{
		CONTINUE_DETECT,
		BREAK_DETECTION,
	};

	class IKDetectEngine : public IUnknown 
	{
	public:
		STDMETHOD_(DETCC,Invoke)( IKDetectSession * sess ) = 0;
		DECLARE_IID;
	};

	// {8AC2B7E9-DC10-48DF-B55C-B8EB141DAF55}
	DEFINE_IID(IKDetectEngine, "{8AC2B7E9-DC10-48DF-B55C-B8EB141DAF55}",
		0x8ac2b7e9, 0xdc10, 0x48df, 0xb5, 0x5c, 0xb8, 0xeb, 0x14, 0x1d, 0xaf, 0x55);

	//class IKEngine : public IUnknown
	//{
	//public:
	//	STDMETHOD(Init)( IUnknown * lpConfig ) = 0;
	//	STDMETHOD(CreateSession)( IKBStream* pstm, UINT32 uOptions, IKDetectSession** ppSession ) = 0;
	//	DECLARE_IID;
	//};

	//// {D6E9F3B6-1847-453A-BB5D-6360D897B85B}
	//DEFINE_IID( IKEngine, "{D6E9F3B6-1847-453A-BB5D-6360D897B85B}",
	//	0xd6e9f3b6, 0x1847, 0x453a, 0xbb, 0x5d, 0x63, 0x60, 0xd8, 0x97, 0xb8, 0x5b);
};


#endif